package com.geek.factory.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.geek.factory.annotation.BizLogRecord;
import com.geek.factory.constant.SuccessConstant;
import com.geek.factory.entity.StockIn;
import com.geek.factory.entity.StockInDetail;
import com.geek.factory.entity.InventoryDistribution;
import com.geek.factory.result.Result;
import com.geek.factory.service.IStockInService;
import com.geek.factory.service.IStockInDetailService;
import com.geek.factory.service.IInventoryDistributionService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 入库单主表控制器
 */
@RestController
@RequestMapping("/stock-in")
@Api(tags = "后台系统的 - 入库单模块")
@Slf4j
@CrossOrigin
public class StockInController {

    @Autowired
    private IStockInService stockInService;

    @Autowired
    private IStockInDetailService stockInDetailService;

    @Autowired
    private IInventoryDistributionService inventoryDistributionService;

    /**
     * 生成入库单编号
     */
    private String generateStockInCode() {
        String prefix = "SI";
        String dateStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        String timeStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("HHmmss"));
        return prefix + dateStr + timeStr;
    }

    @ApiOperation("通过ID查询入库单信息")
    @GetMapping("/{stockInId}")
    public Result findStockInById(@ApiParam("入库单ID") @PathVariable("stockInId") Integer stockInId) {
        StockIn stockIn = stockInService.getById(stockInId);
        log.info("stockIn: {}", stockIn);
        if (stockIn != null) {
            // 查询明细
            QueryWrapper<StockInDetail> detailWrapper = new QueryWrapper<>();
            detailWrapper.eq("stock_in_id", stockInId);
            List<StockInDetail> details = stockInDetailService.list(detailWrapper);

            Map<String, Object> result = new HashMap<>();
            result.put("stockIn", stockIn);
            result.put("details", details);

            return new Result(SuccessConstant.SUCCESS, "ok", result);
        }
        return new Result(SuccessConstant.FAIL, "入库单不存在");
    }

    @ApiOperation("新增入库单")
    @PostMapping
    @Transactional
    @BizLogRecord(value = "入库", description = "新增入库单", logParams = true, logResult = true)
    public Result addStockIn(@RequestBody Map<String, Object> request) {
        try {
            // 解析请求数据
            StockIn stockIn = new StockIn();
            stockIn.setStockInCode(generateStockInCode());
            stockIn.setWarehouseId((Integer) request.get("warehouseId"));
            stockIn.setInType((String) request.get("inType"));
            stockIn.setOperator((String) request.get("operator"));
            stockIn.setRemark((String) request.get("remark"));
            stockIn.setCreatedTime(LocalDateTime.now());
            stockIn.setCreatedBy("admin"); // 实际项目中应从登录用户获取

            // 保存入库单
            boolean isSuccess = stockInService.save(stockIn);
            if (!isSuccess) {
                return new Result(SuccessConstant.FAIL, "保存入库单失败");
            }

            // 保存明细并更新库存
            List<Map<String, Object>> details = (List<Map<String, Object>>) request.get("details");
            if (details != null && !details.isEmpty()) {
                for (Map<String, Object> detailMap : details) {
                    StockInDetail detail = new StockInDetail();
                    detail.setStockInId(stockIn.getStockInId());
                    detail.setProductId((Integer) detailMap.get("productId"));
                    detail.setMaterialId((Integer) detailMap.get("materialId"));
                    detail.setShelfId((Integer) detailMap.get("shelfId"));
                    detail.setQuantity(new BigDecimal(detailMap.get("quantity").toString()));
                    detail.setUnit((String) detailMap.get("unit"));

                    stockInDetailService.save(detail);

                    // 更新库存分布
                    updateInventoryDistribution(detail, stockIn.getWarehouseId(), "add");
                }
            }

            log.info("新增入库单: {}, 结果: {}", stockIn, isSuccess);
            return new Result(SuccessConstant.SUCCESS, "新增成功", stockIn);
        } catch (Exception e) {
            log.error("新增入库单失败", e);
            return new Result(SuccessConstant.FAIL, "新增失败: " + e.getMessage());
        }
    }

    /**
     * 更新库存分布
     */
    private void updateInventoryDistribution(StockInDetail detail, Integer warehouseId, String operation) {
        try {
            QueryWrapper<InventoryDistribution> wrapper = new QueryWrapper<>();
            wrapper.eq("warehouse_id", warehouseId);
            wrapper.eq("shelf_id", detail.getShelfId());

            if (detail.getProductId() != null) {
                wrapper.eq("product_id", detail.getProductId());
            } else if (detail.getMaterialId() != null) {
                wrapper.eq("material_id", detail.getMaterialId());
            }

            InventoryDistribution inventory = inventoryDistributionService.getOne(wrapper);

            if (inventory == null) {
                // 创建新的库存记录
                inventory = new InventoryDistribution();
                inventory.setWarehouseId(warehouseId);
                inventory.setShelfId(detail.getShelfId());
                inventory.setProductId(detail.getProductId());
                inventory.setMaterialId(detail.getMaterialId());
                inventory.setQuantity(detail.getQuantity());
                inventory.setCreatedTime(LocalDateTime.now());
                inventory.setCreatedBy("admin");
                inventoryDistributionService.save(inventory);
            } else {
                // 更新现有库存
                if ("add".equals(operation)) {
                    inventory.setQuantity(inventory.getQuantity().add(detail.getQuantity()));
                } else if ("subtract".equals(operation)) {
                    inventory.setQuantity(inventory.getQuantity().subtract(detail.getQuantity()));
                }
                inventory.setUpdatedTime(LocalDateTime.now());
                inventory.setUpdatedBy("admin");
                inventoryDistributionService.updateById(inventory);
            }
        } catch (Exception e) {
            log.error("更新库存分布失败", e);
            throw e; // 重新抛出异常，以便事务可以回滚
        }
    }

    @ApiOperation("根据ID删除入库单")
    @DeleteMapping("/{stockInId}")
    @Transactional
    @BizLogRecord(value = "入库", description = "删除入库单", logParams = true, logResult = true)
    public Result deleteStockIn(@ApiParam("入库单ID") @PathVariable("stockInId") Integer stockInId) {
        try {
            // 先查询明细，用于恢复库存
            QueryWrapper<StockInDetail> detailWrapper = new QueryWrapper<>();
            detailWrapper.eq("stock_in_id", stockInId);
            List<StockInDetail> details = stockInDetailService.list(detailWrapper);

            StockIn stockIn = stockInService.getById(stockInId);

            // 恢复库存
            for (StockInDetail detail : details) {
                updateInventoryDistribution(detail, stockIn.getWarehouseId(), "subtract");
            }

            // 删除明细
            stockInDetailService.remove(detailWrapper);

            // 删除入库单
            boolean isSuccess = stockInService.removeById(stockInId);
            log.info("删除入库单ID: {}, 结果: {}", stockInId, isSuccess);
            if (isSuccess) {
                return new Result(SuccessConstant.SUCCESS, "删除成功");
            }
            return new Result(SuccessConstant.FAIL, "删除失败");
        } catch (Exception e) {
            log.error("删除入库单失败", e);
            return new Result(SuccessConstant.FAIL, "删除失败: " + e.getMessage());
        }
    }

    @ApiOperation("修改入库单信息")
    @PutMapping("/{stockInId}")
    @Transactional
    @BizLogRecord(value = "入库", description = "修改入库单", logParams = true, logResult = true)
    public Result updateStockIn(@ApiParam("入库单ID") @PathVariable("stockInId") Integer stockInId, @RequestBody Map<String, Object> request) {
        try {
            StockIn stockIn = new StockIn();
            stockIn.setStockInId(stockInId);
            stockIn.setWarehouseId((Integer) request.get("warehouseId"));
            stockIn.setInType((String) request.get("inType"));
            stockIn.setOperator((String) request.get("operator"));
            stockIn.setRemark((String) request.get("remark"));

            boolean isSuccess = stockInService.updateById(stockIn);
            log.info("修改入库单: {}, 结果: {}", stockIn, isSuccess);
            if (isSuccess) {
                return new Result(SuccessConstant.SUCCESS, "修改成功", stockIn);
            }
            return new Result(SuccessConstant.FAIL, "修改失败");
        } catch (Exception e) {
            log.error("修改入库单失败", e);
            return new Result(SuccessConstant.FAIL, "修改失败: " + e.getMessage());
        }
    }

    @ApiOperation("分页查询入库单列表")
    @GetMapping("/page")
    public Result getStockInPage(
            @RequestParam(defaultValue = "1") Integer current,
            @RequestParam(defaultValue = "10") Integer size,
            @RequestParam(required = false) String stockInCode,
            @RequestParam(required = false) String inType
    ) {
        QueryWrapper<StockIn> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(stockInCode)) {
            wrapper.like("stock_in_code", stockInCode);
        }
        if (StringUtils.isNotBlank(inType)) {
            wrapper.eq("in_type", inType);
        }
        wrapper.orderByDesc("created_time");

        Page<StockIn> page = stockInService.page(new Page<>(current, size), wrapper);
        Map<String, Object> data = new HashMap<>();
        data.put("records", page.getRecords());
        data.put("total", page.getTotal());
        data.put("current", page.getCurrent());
        data.put("size", page.getSize());
        data.put("pages", page.getPages());

        return new Result(SuccessConstant.SUCCESS, "查询成功", data);
    }

    @ApiOperation("获取所有入库单列表")
    @GetMapping("/list")
    public Result getAllStockIns() {
        List<StockIn> stockIns = stockInService.list();
        return new Result(SuccessConstant.SUCCESS, "查询成功", stockIns);
    }
}